<template>
	<a-form-item :class="[hasError ? 'hhg-form-item-has-error' : '']" :label="labelName" :name="name" :rules="rules">
		<div class="uploadList">
			<div class="theme-txt" @click="uploadFn" v-if="!isRead">
				<span class="ico">上传附件</span>
			</div>
			<div v-if="hasList.length !== 0">
				<div class="theme-txt" v-for="item in hasList" :key="item.id"  @click="nodeClick(item)">
					<a-popconfirm :title="deleteTipsTitle" overlayClassName="hhg-upload-tips" :ok-text="okText" :cancel-text="cancelText"
						@confirm="removeUpload(item.id)" @click.stop v-if="!isRead">
						<template #icon></template> <!-- 传入空内容以移除图标 -->
						<div class="removeUploadItem"></div>
					</a-popconfirm>
					<span>{{ item.fileName }}</span>
				</div>
			</div>
		</div>
	</a-form-item>
	<a-modal centered :width="600" v-model:visible="isupload" bodyStyle="padding:0" :footer="null" ref="modalRef"
		:wrap-style="{ overflow: 'hidden' }">
		<div class="modalUpload">
			<div class="uploadbody">
				<div class="uploadmain" :class="[errorTips ? 'hasErrorTips' : '']">
					<a-upload v-bind="attrs" :action="null" v-model:file-list="fileList" name="file" :multiple="multiple"
						id="uploadID" :beforeUpload="beforeUpload" @change="successHandle"
						@remove="handleRemove" :on-success="successHandle" :progress="progress"
						class="uploadCom">
						<div></div>
						<!-- 自定义文件列表项 -->
						<template #itemRender="{ file, actions }">
							<div class="upload-fileList">
								<div class="upload-fileListItem">
									<div class="upload-fileListItem-header">
										<div>{{ file.name }}({{ formatBytes(file.size) }})</div>
										<div v-if="file.status === 'done'">completed</div>
										<div v-if="file.status === 'error'">failed</div>
										<div @click="actions.remove" class="upload-removeItem"></div>
									</div>
									<a-progress class="hhgProgress" :percent="file.percent || 0" :status="file.status === 'error' ? 'exception' : ''" />
								</div>
							</div>
						</template>
					</a-upload>
					<div class="progress" v-if="loading">
						<a-progress :percent="progressPercent" status="active" v-if="showProgress" />
					</div>
					<div class="line" v-if="errorTips">
						<div>
							<span class="error">{{ errorTips }}</span>
						</div>
					</div>

				</div>
			</div>
			<div class="uploadFoot">

				<a-button :style="{ background: '#3f7fbf', border: '0', color: '#fff' }" type="primary"
					@click="viewUpload">浏览文件</a-button>
				<a-button :style="{ background: '#3f7fbf', border: '0', color: '#fff', margin: '0 5px' }"
					type="primary" :loading="uploading" @click="startUploadNew">开始上传</a-button>
				<a-button :style="{ background: '#3f7fbf', border: '0', color: '#fff', margin: '0 5px' }"
					type="primary" @click="cancelRequest">取消上传</a-button>
				<a-button :style="{ background: '#cbcbcb', border: '0', color: '#666' }"
					@click="closeModal">关闭</a-button>
			</div>
		</div>
		<!-- 拖动 -->
		<template #title>
			<div ref="modalTitleRef" style="width: 100%; cursor: move">上传附件</div>
		</template>
		<template #modalRender="{ originVNode }">
			<div :style="transformStyle">
				<component :is="originVNode" />
			</div>
		</template>
	</a-modal>
</template>
<script setup>
import { defineEmits, ref, onMounted, defineProps, useAttrs, watch, watchEffect, computed } from 'vue'
import axios from 'axios'
//拖动
import { useDraggable } from '@vueuse/core'
const emit = defineEmits(['update:modelValue', 'nodeClick'])
const nodeClick = item=> {
	emit('nodeClick', item)
}
const props = defineProps({
	config: {
		type: Object,
		default: () => { },
		multiple: {
			type: Boolean,
			default: () => false
		}
	}
})
const attrs = useAttrs()

const labelName = ref(props.config.labelName)
const hasError = ref(props.config.hasError ? props.config.hasError : false)
const name = ref(props.config.name)
const rules = ref(props.config.rules)
const multiple = ref(props.config.multiple)
const isRead = ref(null)
const deleteTipsTitle = ref(props.config.deleteTipsTitle ? props.config.deleteTipsTitle : '确定删除当前文件？')
const okText = ref(props.config.okText)
const cancelText = ref(props.config.cancelText)
const hhgUploadUrl = ref(props.config.uploadUrl)
watch(() => props.config.isRead, (val) => {
  if (val) {
	isRead.value = val
  }
}, { immediate: true }, { deep: true })

const viewUpload = () => {
	document.getElementById('uploadID').click()
}
// const getFileList = ref([])
const progressPercent = ref(2)
const startUploadNew = ()=> {
	if (fileList.value.length === 0) return
	fileList.value.forEach(file=> {
		
		customRequest(file)
	})
}
//取消axios
let axiosSource = axios.CancelToken.source()

// 当你需要取消请求时调用
const cancelRequest = ()=> {
	axiosSource.cancel('取消请求')
	uploading.value = false
	isupload.value = false
}

// 封装upload方法
const customRequest = (file) => {
	const formData = new FormData()
      formData.append('file', file.originFileObj)
      formData.append('contentType', file.type)
	Object.keys(props.config?.jsonApi).forEach(key => {
		formData.append(key, props.config.jsonApi[key])
	})
	axiosSource = axios.CancelToken.source()
      progressPercent.value = 0 // Reset progress before upload
	axios.post(hhgUploadUrl.value, formData, {
		cancelToken: axiosSource.token,
		headers: { 
			'Content-Type': 'multipart/form-data',
			'X-Requested-With': 'XMLHttpRequest'
		},
		onUploadProgress: (progressEvent) => {
			if (progressEvent.lengthComputable) {
				const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
				const updatedFile = fileList.value.find(f => f.uid === file.uid)
				if (updatedFile) {
					updatedFile.percent = percentCompleted
					setTimeout(() => {
						updatedFile.percent = 100
					}, 500)
				}
			}
		}
	})
	.then(res => {
		count.value++
		if (res.data.code && res.data.code === 20000) {
			countSuccess.value++
			hasList.value = [...hasList.value, res.data.data]
			emit('update:modelValue', hasList.value)
			emit('uploadSucces', hasList.value)
			const updatedFile = fileList.value.find(f => f.uid === file.uid)
			if (updatedFile) {
				updatedFile.status = 'done'
			}
		}
	})
	.catch((error) => {
		count.value++
		if (axios.isCancel(error)) {
			console.log('Request canceled', error.message)
		} else {
			// 处理其他错误
			console.error(error)
		}
		// const updatedFile = fileList.value.find(f => f.uid === file.uid)
		// if (updatedFile) {
		// 	updatedFile.status = 'error'
		// }
	})
}
const count = ref(0)
const countSuccess = ref(0)
function formatBytes (bytes) {//单位转换
    if (bytes === 0) return '0 B'

    const k = 1024
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))

    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
const closeModal = () => {
	if(fileList.value.length === 0) {
		isupload.value = false
	}
	if(count.value !== 0 && (count.value === fileList.value.length)) {
		isupload.value = false
	}
}
//上传点击
const errorTips = ref('')
const fileList = ref([])
const hasList = ref([])
watch(() => props.config, (val) => {
	if(val.hasList) {
		hasList.value = val.hasList
	}
}, { immediate: true }, { deep: true })
const isupload = ref(false)
const uploadFn = () => {
	
	count.value = 0
	countSuccess.value = 0
	if (isRead.value) return
	fileList.value = []
	isupload.value = !isupload.value
}
const removeUpload = (id) => {
	if (isRead.value) return
	// 找到要删除的元素的索引
	const index = hasList.value.findIndex(item => item.id === id)
	// 如果找到了索引，使用 splice 方法删除该元素
	if (index !== -1) {
		hasList.value.splice(index, 1)
	}
	emit('update:modelValue', hasList.value)
}
//上传进度条
const showProgress = ref(false)
const progress = {
	strokeColor: {
		'0%': '#108ee9',
		'100%': '#87d068',
	},
	strokeWidth: 3,
	format: percent => `${parseFloat(percent.toFixed(2))}%`,
	class: 'test',
}
//文件类型检测
const allowedTypes = ref(props.config.fileAccept)
const hhgFileSize = ref(props.config.fileSize)

const handleRemove = file => {
	
	const index = fileList.value.indexOf(file)
	const newFileList = fileList.value.slice()
	newFileList.splice(index, 1)
	fileList.value = newFileList
}
const beforeUpload = file => {
	file.status = file.status === 'error' ? '' : file.status
	// 获取最后一个点的位置
	const lastDotIndex = file.name.lastIndexOf('.')
	// 如果存在点，则提取扩展名；否则返回空字符串
	const fileExtension = lastDotIndex !== -1 ? file.name.substring(lastDotIndex) : ''
	// 检查扩展名是否在允许的列表中
	const isAllowedType = allowedTypes.value?.includes(fileExtension.toLowerCase())
	if (hhgFileSize.value && allowedTypes.value) {
		
		
		if (isAllowedType && (file.size < hhgFileSize.value || file.size === hhgFileSize.value)) {
			return true
		} else {
			if (!isAllowedType) {
				errorTips.value = props.config.errorTipsText
				setTimeout(() => {
					errorTips.value = ''
				}, 3000)
				return false
			}
			if (file.size > hhgFileSize.value) {
				errorTips.value = props.config.errorTipsSize
				setTimeout(() => {
					errorTips.value = ''
				}, 3000)
				return false
			}
		}
	}
	if (hhgFileSize.value && !allowedTypes.value) {
		if (file.size > hhgFileSize.value) {
			errorTips.value = props.config.errorTipsSize
			setTimeout(() => {
				errorTips.value = ''
			}, 3000)
			return false
		}
	}
	if (!hhgFileSize.value && allowedTypes.value) {
		if (!isAllowedType) {
			errorTips.value = props.config.errorTipsText
			setTimeout(() => {
				errorTips.value = ''
			}, 3000)
			return false
		}
	}
	return true
};
const successHandle = info => {
	const { fileList: newFileList } = info;
	// 过滤掉不符合要求的文件
	const filteredFileList = newFileList.filter(file => {
		const isAllowedType = beforeUpload(file)
		return isAllowedType
	})
	fileList.value = filteredFileList
	showProgress.value = false
}
const uploading = ref(false)
// const startUpload = () => {
// 	if (fileList.value.length === 0) return
// 	emit('startUpload', fileList.value)
// }
watch(() => countSuccess.value, (val) => {
	if (val) {
		if (val === fileList.value.length) {
			setTimeout(() => {
				isupload.value = false
			}, 1000)
		}
	}
}, { immediate: true }, { deep: true })

//拖动
const modalTitleRef = ref(null)
const { x, y, isDragging } = useDraggable(modalTitleRef)
const startX = ref(0)
const startY = ref(0)
const startedDrag = ref(false)
const transformX = ref(0)
const transformY = ref(0)
const preTransformX = ref(0)
const preTransformY = ref(0)
const dragRect = ref({
	left: 0,
	right: 0,
	top: 0,
	bottom: 0
})
watch([x, y], () => {
	if (!startedDrag.value) {
		startX.value = x.value
		startY.value = y.value
		const bodyRect = document.body.getBoundingClientRect()
		const titleRect = modalTitleRef.value.getBoundingClientRect()
		dragRect.value.right = bodyRect.width - titleRect.width
		dragRect.value.bottom = bodyRect.height - titleRect.height
		preTransformX.value = transformX.value
		preTransformY.value = transformY.value
	}
	startedDrag.value = true
})
watch(isDragging, () => {
	if (!isDragging) {
		startedDrag.value = false
	}
})
watchEffect(() => {
	if (startedDrag.value) {
		transformX.value =
			preTransformX.value +
			Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) -
			startX.value;
		transformY.value =
			preTransformY.value +
			Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) -
			startY.value
	}
})
const transformStyle = computed(() => {
	return {
		transform: `translate(${transformX.value}px, ${transformY.value}px)`
	}
})

onMounted(() => { })
</script>
<style lang="scss"></style>